package com.idc.resource.help;

import com.idc.resource.enums.ErrorCodeEnum;
import com.idc.resource.exception.IdcServiceException;
import com.idc.resource.help.api.SmsMsgSendApi;
import com.idc.resource.help.model.SmsMsgConfig;
import com.idc.resource.help.model.SmsMsgInfo;
import com.idc.resource.util.AliCloudSmsUtil;
import com.idc.resource.util.RetrofitUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.Retrofit;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 短信发送
 * Created by Administrator on 2017/7/16 0016.
 */
@Slf4j
@Component
public class SmsMsgHelp {
    /** 短信发送配置 */
    private final SmsMsgConfig smsMsgConfig;
    /** 请求地址api */
    private final SmsMsgSendApi smsMsgSendApi;

    @Autowired
    public SmsMsgHelp(SmsMsgConfig smsMsgConfig) {
        this.smsMsgConfig = smsMsgConfig;
        Retrofit retrofit = RetrofitUtil.createRetrofit(null, smsMsgConfig.getDomainUrl());
        smsMsgSendApi = retrofit.create(SmsMsgSendApi.class);
    }

    /**
     * 短信验证码发送
     * @param smsMsgInfo 短信验证码发送请求对象
     * @return true 发送成功 false 发送失败
     */
    public boolean sendAuthCodeMsg(SmsMsgInfo smsMsgInfo){
        try {
            Map<String,String> queryMap = buildSignString(smsMsgInfo);
            Call<Object> call = smsMsgSendApi.sendMsg(queryMap);
            Response<Object> response = call.execute();
            if(response.code()==200){
                log.info("短信发送接口请求成功:{}",response.body());
                return true;
            }
            log.error("短信发送接口失败:{}",response.errorBody().string());
            return false;
        }catch (Exception e){
            log.error("短信验证码发送失败，原因：",e);
            throw new IdcServiceException(ErrorCodeEnum.SYSTEM_ERROR.getCode(),ErrorCodeEnum.SYSTEM_ERROR.getDesc());
        }
    }

    /**
     * 组建短信接口加密请求参数串
     * @param smsMsgInfo 短信请求
     * @return 请求参数加密串
     */
    private Map<String, String> buildSignString(SmsMsgInfo smsMsgInfo){
        try {
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
            df.setTimeZone(new SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区
            Map<String, String> paras = new HashMap<>();
            // 1. 系统参数
            paras.put("SignatureMethod", "HMAC-SHA1");
            paras.put("SignatureNonce", UUID.randomUUID().toString());
            paras.put("AccessKeyId", smsMsgConfig.getAccessKeyId() );
            paras.put("SignatureVersion", "1.0");
            paras.put("Timestamp", df.format(new Date()));
            paras.put("Format", "JSON");
            // 2. 业务API参数
            paras.put("Action", "SendSms");
            paras.put("Version", "2017-05-25");
            paras.put("RegionId", "cn-hangzhou");
            paras.put("PhoneNumbers", smsMsgInfo.getPhoneNum());
            paras.put("SignName", smsMsgConfig.getSignName());
            paras.put("TemplateParam", "{\"code\":\""+ smsMsgInfo.getAuthCode()+"\"}");
            paras.put("TemplateCode", smsMsgConfig.getTemplateCode());
            paras.put("OutId", "123");

            TreeMap<String, String> sortParas = new TreeMap<>();
            sortParas.putAll(paras);
            Iterator<String> it = sortParas.keySet().iterator();
            StringBuilder sortQueryStringTmp = new StringBuilder();
            while (it.hasNext()) {
                String key = it.next();
                sortQueryStringTmp.append("&").append(AliCloudSmsUtil.specialUrlEncode(key)).append("=").append(AliCloudSmsUtil.specialUrlEncode(paras.get(key)));
            }
            String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号
            String stringToSign = "GET" + "&" +
                    AliCloudSmsUtil.specialUrlEncode("/") + "&" +
                    AliCloudSmsUtil.specialUrlEncode(sortedQueryString);
            String sign = AliCloudSmsUtil.sign(smsMsgConfig.getAccessKeySecret() + "&", stringToSign);
            paras.put("Signature",sign);
            return paras;
        }catch (Exception e){
            log.error("阿里云短信请求参数加密失败，原因：",e);
            return null;
        }
    }



}
